home *** CD-ROM | disk | FTP | other *** search
- #include "util.h"
- #include "mmdf.h"
-
- /*
- * MULTI-CHANNEL MEMO DISTRIBUTION FACILITY (MMDF)
- *
- *
- * Copyright (C) 1979,1980,1981 University of Delaware
- *
- * Department of Electrical Engineering
- * University of Delaware
- * Newark, Delaware 19711
- *
- * Phone: (302) 738-1163
- *
- *
- * This program module was developed as part of the University
- * of Delaware's Multi-Channel Memo Distribution Facility (MMDF).
- *
- * Acquisition, use, and distribution of this module and its listings
- * are subject restricted to the terms of a license agreement.
- * Documents describing systems using this module must cite its source.
- *
- * The above statements must be retained with all copies of this
- * program and may not be removed without the consent of the
- * University of Delaware.
- *
- *
- * version -1 David H. Crocker March 1979
- * version 0 David H. Crocker April 1980
- * version v7 David H. Crocker May 1981
- * version 1 David H. Crocker October 1981
- *
- */
- /* SUBMIT: Mail enqueuer
- *
- * May, 80 Dave Crocker fix switch-setting in prm_ & pro_
- * add eof check after text copy
- * adr_ghost return PAST initial string ->
- * modify use of pointer to be -1
- * Jun, 80 Dave Crocker fix adr_ghost return to be 1 past
- * mn_init, change fout to be 2, not dup(1)
- * hdr_psfrom handle FLGFROM properly
- * Jul, 80 Dave Crocker prm_parse, remove debug & fix default
- * Sep, 80 Jim Lieb Conversion to V7 and standard io
- * protocol replies go to stderr
- * Oct, 80 Dave Crocker Minor mods to make V6 also (again) work
- * Nov, 80 Dave Crocker Split off adr_submit, qf_submit, mgt_submit,
- * & hdr_parse, for easier policy changes
- * Nov, 81 Dave Crocker Switches case-insensitive
- * Jun 82 Dave Crocker Add adruid proc/file address protection
- * Jul 82 Dave Crocker qf_ -> mq_
- */
-
- #include <sys/stat.h>
- #include <pwd.h>
- #include "nexec.h"
- #include "ap.h"
- #include "ns.h"
-
- extern LLog msglog;
- LLog *logptr = &msglog;
- extern struct ap_prevstruct *ap_fle; /* parse state top of stack */
-
- extern char *locfullname;
- extern char *locfullmachine;
- extern char *quedfldir; /* directory w/mail queue directories */
- extern char *cmddfldir; /* directory w/mmdf commands */
- extern char *logdfldir; /* directory w/mmdf log files */
- extern char *supportaddr;
- extern char *sitesignature;
-
- jmp_buf retloc; /* address for longjmp() */
- int userid, /* id of user running me */
- effecid, /* id providing access priviledges */
- adruid; /* authorized addr, for file access */
-
- char *username; /* string login name of user running me */
- char *mailid; /* string mailid of user running me */
-
- short earlyret, /* caller already got return status */
- readadrs, /* will be directly fed address list */
- tracing; /* enable submission tracing on fd2 */
-
- extern char *mgt_parm();
- extern char *dupfpath();
- extern char *strdup();
- extern char *multcat();
- extern char *getmailid();
- extern char *malloc();
- extern char *strdup();
- extern struct passwd *getpwuid();
- extern ap_flget();
-
- extern char *namdeliver; /* name of mailer process */
- extern char *pathdeliver; /* file path to mailer proc. */
- extern int *regfdary;
- extern int errno;
- extern int sys_nerr;
- extern char *sys_errlist[];
-
- char *prm_dupval();
-
- LOCFUN prm_parse(), hdr_isacmpt();
-
- /* *** constants and temporaries *** */
- char nltrm[] = "\n\377", /* for gcread() */
- nlnultrm[] = "\n\000\377",
- nultrm[] = "\000\377";
-
- /* *** pro_ *** */
- short pro_doing = TRUE, /* protocol-mode interaction vs. one- */
- /* message "batch" submission? */
- pro_vfadr; /* in protocol mode, indicate */
- /* acceptance of each address */
- char pro_buf[BUFSIZ]; /* buffer pro_ output */
-
- /**/
- /* *** mq_ *** */
-
- extern FILE *mq_mffp; /* pointerto message text file buffer */
- extern char *mq_munique; /* unique part of message queue name */
-
- /* *** ch_ *** */
- #include "ch.h"
- extern Chan **ch_tbsrch;
-
- /* *** adr_ *** */
- #include "adr_queue.h"
- #include "msg.h"
- extern char *adr_fulldmn; /* SEK - name for 'full' domain name */
- extern char *adr_fmc; /* name of 'full' machine */
-
- /* *** tx_ *** */
- long tx_msize;
-
- /* *** hdr_ *** */
- #include "hdr.h"
- #define MAXACMPT 10
-
- char *hdr_cmpt[MAXACMPT]; /* where to extract addresses from */
-
- short hdr_numadrcmpt; /* number of components to search */
- /* for addresses in msg text */
- short hdr_extractadr; /* tx_stormsg extract addrs? */
-
- /* *** mgt_ *** */
- extern char *mgt_txsrc; /* text to add to Source-Info cmpnt */
- extern int mgt_inalias; /* SEK - is address extracted from */
- /* alias file */
-
- /* *** auth_ *** */
- extern char auth_msg[]; /* message of reason for auth refusal */
-
- /* *** dlv_ *** */
- short dlv_watch; /* user want to watch the send? */
- int dlv_flgs; /* flags to store into first line */
- /* of address list (e.g. RETCITE) */
-
- /* *** ut_ *** */
- char *ut_alloc ();
- short ut_eofhit, /* eof encountered on ut_stdin */
- ut_msgend; /* null/eof encountered on ut_stdin */
-
- /******* (mn_) MAIN MAIN MAIN MAIN MAIN MAIN MAIN MAIN MAIN ****** */
-
- LOCVAR char *mn_aptr; /* current position on buffer */
- LOCVAR char mn_abuf[LINESIZE]; /* address buffer */
-
- LOCFUN
- mn_adrin () /* main input given to alst_proc */
- {
- if (mn_aptr == (char *)1) {
- #ifdef DEBUG
- ll_log (logptr, LLOGFTR, "mn_adrin need newline");
- #endif
- if (ut_stdin(mn_abuf, sizeof(mn_abuf), nltrm, NOTOK) <= 0
- || strequ ("!\n", mn_abuf))
- mn_aptr = (char *) 0; /* disable future reading */
- else
- mn_aptr = mn_abuf;
- }
- if (mn_aptr == (char *)0) {
- #ifdef DEBUG
- ll_log (logptr, LLOGBTR, "mn_adrin eof or err");
- #endif
- return (0); /* permanent eof */
- }
-
- switch (*mn_aptr) {
- case '\n':
- case '\0': /* end on bang/newline/bang */
- mn_aptr = (char *)1; /* indicate we need another line */
- return (0); /* note end of this address */
- }
-
- return (*mn_aptr++);
- }
-
- /*
- * Function to re-sync input. This is needed for the interactive
- * input function because the other side is expecting exactly one
- * reply per line sent. alst_proc might parse two addresses in one line.
- */
- mn_arset()
- {
- mn_aptr = (char *)1;
- }
-
- mn_aread ()
- {
- mn_aptr = (char *)1; /* flag as needing a new line */
- mgt_inalias = FALSE; /* reading addresses from input */
-
- (void) alst_proc (mn_adrin, TRUE, mn_arset, (char **) 0);
-
- mn_aptr = (char *) 0;
- }
-
- /**/
-
- main (argc, argv) /* MAIN MAIN MAIN MAIN MAIN MAIN */
- int argc;
- char *argv[];
- {
- umask(0);
- mmdf_init (argv[0]);
- #ifdef NAMESERVER
- ns_settimeo(NS_UIPTIME); /* set an initial timeout */
- #endif
- mn_usinit (); /* initial info on who is running us */
- mn_init (argc, argv); /* parse args, alloc buffers. */
- mn_dirinit (); /* chdir into quedfldir */
- mgt_init ();
- mq_winit (); /* info on queue directories */
-
- for (setjmp (retloc); /* return here, after err_msg */
- !ut_eofhit;) /* no more input? */
- {
- if (pro_doing)
- if (pro_init () != OK)
- break; /* all done */
-
- mq_creat (); /* set-up the queue files including */
- /* status info in address list */
-
- if (readadrs) /* explicit address list being given? */
- mn_aread ();
-
- if (ut_msgend) /* can't do much with only addr list */
- err_abrt (RP_EOF, "Input ended prior to processing text");
-
- tx_stormsg (); /* queue & authenticate message */
-
- if (pro_doing && ut_eofhit)
- err_abrt (RP_EOF, "Premature eof during text copy");
-
- mgt_aend (); /* perform any ending address policy */
-
- lnk_filall (dlv_flgs);
- /* put address list into its file */
-
- lnk_freeall ();
-
- mq_eomsg (); /* move to real queue directory */
-
- #ifdef DEBUG
- ll_log (logptr, LLOGPTR, "msg done -- do deliver?");
- #endif
-
- dlv_invoke (); /* Maybe give the message a mailer */
- /* Will acknowledge message queueing */
- }
- exit (RP_OK);
- }
- /**/
-
- mn_init (argc, argv) /* basic process initialization */
- int argc;
- char *argv[];
- {
- register short tmp;
-
- prm_init (); /* set default values */
- for (tmp = 1; tmp < argc; tmp++)
- { /* parse any arguments */
- if (*argv[tmp] == '-')
- {
- pro_doing = FALSE; /* presence of arguments => one-shot */
- prm_parse (&argv[tmp][1]);
- } /* parse the switch string */
- else
- mgt_parm (argv[tmp]); /* let management module analyze it */
- }
-
- if (!pro_doing) /* protocol mode will do its own */
- prm_end (); /* cleanup & evaluate state */
- }
- /**/
-
- mn_usinit () /* get info on who is running me */
- {
- register char *midp;
- register struct passwd *pw;
-
- getwho (&userid, &effecid); /* who is running me? */
- #ifdef DEBUG
- ll_log (logptr, LLOGBTR, "user=%d, effec=%d", userid, effecid);
- #endif
-
- if((pw = getpwuid(userid)) == NULL
- || (midp = getmailid(pw->pw_name)) == NULL)
- err_abrt (RP_LIO, "No login/mailid for UID %d, call Support.",
- userid);
-
- username = strdup (pw -> pw_name);
- mailid = strdup (midp);
-
- if (effecid == userid) /* being run by MMDF */
- adruid = 0; /* full privileges */
- else
- adruid = userid; /* uid for file/process redirection */
- #ifdef UCL
- if (adruid == 2) /* fix for authorization for UCL */
- adruid = 0;
- #endif
- }
-
- mn_dirinit () /* current loc? chdir to home; setuid */
- {
- if (chdir (quedfldir) == NOTOK) /* change wdir into mail queues */
- err_abrt (RP_LIO, "Unable to change directory.");
-
- setuid (userid); /* so we have the user's privileges */
- /* to access address files */
- }
- /******************* (prm_) USER PARAMETER HANDLING *************** */
-
- prm_init () /* set default user-settable vals */
- {
-
- mgt_minit (); /* initialize management settings */
-
- while (hdr_numadrcmpt-- > 0) /* free any previous component names */
- free (hdr_cmpt[hdr_numadrcmpt]);
-
- hdr_numadrcmpt =
- dlv_flgs = 0;
-
- readadrs =
- hdr_extractadr =
- pro_vfadr =
- dlv_watch =
- earlyret = FALSE;
-
- adr_fulldmn = locfullname;
- if (locfullmachine && isstr (locfullmachine))
- adr_fmc = locfullmachine;
- else
- adr_fmc = locfullname;
- }
-
- prm_end () /* evaluate final settings */
- {
- if (!pro_doing) /* no protocol => a unix "command" */
- domsg = TRUE;
-
- if (!hdr_extractadr) /* not building list from msg text, */
- readadrs = TRUE; /* so take from explicit list */
-
- mgt_pend (); /* end of parm specifications */
- }
- /**/
-
- LOCFUN
- prm_parse (parmstrt) /* parse spec & set switches */
- char *parmstrt; /* note beginning of parm */
- {
- register char *parmptr; /* pointer to text of specification */
-
- parmptr = parmstrt;
- FOREVER
- switch (*parmptr++) /* read until end of list */
- {
- case '\0':
- case '\n':
- return; /* all done */
- case ' ':
- case '\t': /* skip linear white space */
- case '-': /* switch-char got through */
- continue;
-
- case 'L': /* Specify alternate logfile, SU/MMDF only */
- if (adruid == 0 && *parmptr) {
- char *cp;
-
- switch (*(parmptr = prm_dupval(parmptr, &cp)))
- {
- case ',': /* skip to the last char processed */
- err_msg (RP_PARM, "Invalid parameter character ','");
-
- case '*':
- parmptr++;
- }
- ll_log (logptr, LLOGFST, "Logfile is '%s'", cp);
- logptr->ll_file = dupfpath(cp, logdfldir);
- }
- break;
-
- case 'V': /* Specify alternate level, SU/MMDF only */
- if (adruid == 0 && *parmptr) {
- char *cp;
- int level;
-
- switch (*(parmptr = prm_dupval(parmptr, &cp)))
- {
- case ',': /* skip to the last char processed */
- err_msg (RP_PARM, "Invalid parameter character ','");
-
- case '*':
- parmptr++;
- }
- ll_log (logptr, LLOGFST, "Loglevel '%s'", cp);
- if ((level = tai_llev (1, &cp)) > 0)
- logptr->ll_level = level;
- }
- break;
-
- case 'W':
- tracing = TRUE;
- break;
-
- case 'b': /* deliver to mailbox AND tty (obsolete) */
- break;
-
- case 'c': /* only CITATION in returm mail, not */
- dlv_flgs |= ADR_CITE;
- break; /* full copy of text */
-
- case 'd': /* don't force through DELAY channel */
- mgt_parm ("d");
- break;
-
- case 'f': /* add FROM text to Source-Info field */
- switch (*(parmptr = prm_dupval (parmptr, &mgt_txsrc)))
- {
- case ',':
- case '*':
- parmptr++;
- }
- break;
-
- case 'h': /* hostname of relay source */
- switch (*(parmptr = mgt_parm (&parmptr[-1])))
- { /* let management module process it */
- case ',': /* skip to the last char processed */
- err_msg (RP_PARM, "Invalid parameter character ','");
-
- case '*':
- parmptr++;
- }
- break;
-
- case 'i': /* RELAYING, "via" us, "INDIRECTLY" */
- switch (*(parmptr = mgt_parm (&parmptr[-1])))
- { /* let management module process it */
- case ',': /* skip to the last char processed */
- err_msg (RP_PARM, "Invalid parameter character ','");
-
- case '*':
- parmptr++;
- }
- break;
-
- case 'j': /* we are the delay channel !! */
- mgt_parm ("j");
- break;
-
- case 'k': /* Set nameserver timeouts */
- switch (*(parmptr = mgt_parm (&parmptr[-1])))
- { /* let management module process it */
- case ',': /* skip to the last char processed */
- err_msg (RP_PARM, "Invalid parameter character ','");
-
- case '*':
- parmptr++;
- }
- break;
-
- case 'l': /* send LOCAL mail immediately */
- mgt_parm ("l"); /* fork a mailer for it */
- break;
-
- case 'm': /* send just to MAILBOX (obsolete option) */
- break;
-
- case 'n': /* send "NET" mail immediately */
- mgt_parm ("n"); /* fork a mailer for it */
- break;
-
- case 'q': /* do not return a copy on errors */
- dlv_flgs |= ADR_NORET;
- break;
-
- case 'r': /* send RETURN mail to invoker */
- mgt_parm ("r"); /* and not explicit specification */
- break;
-
- case 's': /* get RETURN from Sender info */
- mgt_parm ("s"); /* and not explicit specification */
- break;
-
- case 't': /* TRUST me; don't authenticate */
- mgt_parm ("t");
- break;
-
- case 'u': /* (close to 't'); no authentication */
- mgt_parm ("u");
- break;
-
- case 'v': /* Protocol mode; VERIFY each address */
- pro_vfadr = TRUE; /* as received */
- break;
-
- case 'w': /* user wants to WATCH a delivery try */
- dlv_watch = TRUE;
- break;
-
- case 'g': /* GET cmpts addrs AND explicit ones */
- readadrs = TRUE; /* DROP ON TRHOUGH */
- case 'x': /* EXTRACT addrs from cmpnts */
- hdr_extractadr = TRUE; /* 'x' [name *(',' name)] '*' */
- while (hdr_numadrcmpt < MAXACMPT)
- switch (*(parmptr = prm_dupval (parmptr,
- &(hdr_cmpt[hdr_numadrcmpt++]))))
- {
- case ',':
- parmptr++;
- continue;
-
- case '*':
- case '\n':
- parmptr++;
-
- case '\0':
- goto cmptend;
- }
- cmptend:
- hdr_cmpt[hdr_numadrcmpt] = 0;
- break;
-
- case 'z': /* do not send non-delivery warnings */
- dlv_flgs |= ADR_NOWARN;
- break;
-
- default:
- err_msg (RP_PARM, "Invalid parameter character '%c' in '%s'",
- parmptr[-1], parmstrt);
- }
- }
- /**/
-
- char *
- prm_dupval (start, into) /* get text; dup to into; return ptr */
- /* to last char in orig str */
- char *start; /* beginning of text to parse */
- char **into; /* where to put dup'd str */
- {
- register char tchar;
- register char *strptr;
-
- for (strptr = start;; strptr++)
- switch (*strptr)
- {
- case '*':
- case ',':
- case '\0':
- case '\n':
- tchar = *strptr;
- *strptr = '\0';
- *into = strdup (start);
- *strptr = tchar;
- return (strptr); /* pass back pointer to last char */
- }
- }
- /************** (pro_) PROTOCOL WITH CALLER **************** */
-
- pro_init () /* read switches in protocol mode */
- {
- char linebuf[LINESIZE];
-
- #ifdef DEBUG
- ll_log (logptr, LLOGBTR, "pro_init ()");
- #endif
-
- (void) setbuf(stderr,pro_buf);
-
- ut_msgend = FALSE;
-
- if (ut_stdin (linebuf, sizeof linebuf, nlnultrm, NOTOK) == OK)
- return (NOTOK); /* done before we began. tsk. tsk. */
-
- prm_init ();
- prm_parse (linebuf); /* parse & use switches */
- prm_end ();
- return (OK);
- }
- /**/
-
- /* VARARGS2 */
- pro_reply (code, fmt, b, c, d) /* inform user of a status */
- short code; /* value from mmdfrply.h */
- char *fmt,
- *b,
- *c,
- *d;
- {
- register char *errchar;
-
- #ifdef DEBUG
- ll_log (logptr, LLOGBTR, "pro_reply(%s)", rp_valstr (code));
- ll_log (logptr, LLOGFTR, fmt, b, c, d);
- #endif
-
- if (pro_doing) /* print each field, for exactness */
- putc(rp_gval (code), stderr);
- else
- { /* assume human watching */
- if (rp_isgood (code)) /* keep silent during success */
- return;
- fprintf(stderr, "submit: "); /* and noisy on errors */
- }
- if (rp_isbad (code))
- switch (rp_gval (code))
- {
- case RP_HUH: /* not if it was a user error */
- case RP_PARM:
- case RP_USER:
- break;
-
- default:
- if (errno > 0 && errno < sys_nerr)
- /* a system-call error; have to dance */
- { /* around ending \n in sys_errlist */
- fprintf (stderr, "[ ");
- for (errchar = sys_errlist[errno];
- !isnull (*errchar) && *errchar != '\n';
- errchar++)
- putc(*errchar, stderr);
- fprintf (stderr, " ] ");
- }
- }
- fprintf(stderr, fmt, b, c, d);
- putc('\n', stderr);
- fflush(stderr);
- }
- /***************** (alst_) PROCESS AN ADDRESS LIST *************** */
-
- alst_proc (inproc, errabrt, resync, badptr) /* process text stream of addrs */
- int (*inproc) (); /* the function which gets address */
- /* chars; decides when finished */
- int errabrt; /* abort on error? */
- int (*resync) (); /* the function that resyncs input */
- char **badptr; /* place to stuff list of bad addresses */
- {
- AP_ptr local, /* beginning of local-part */
- domain, /* basic domain reference */
- route; /* beginning of 733 forward routing */
- AP_ptr theptr;
- int retval;
- int anybad;
- char *msgptr;
- char *addrp;
- char *cp;
- int inalias;
- char *oldbad;
-
- #ifdef DEBUG
- ll_log (logptr, LLOGBTR, "alst_proc ()");
- #endif
- anybad = RP_AOK;
- inalias = mgt_inalias; /* SEK hold value at this level */
-
- FOREVER
- {
- if ((theptr = ap_pinit (inproc)) == (AP_ptr) NOTOK)
- err_abrt (LLOGTMP, "problem initializing for address parse");
- /* problem during parse */
-
- switch( retval = ap_1adr ())
- { /* get next address */
- case NOTOK:
- ap_sqdelete (theptr, (AP_ptr) 0);
- ap_free (theptr);
- if (!errabrt) /* Keep on trucking... */
- anybad = RP_USER;
- else if (pro_vfadr) /* just tell caller & continue */
- err_gen (RP_USER, "Unable to parse address");
- else /* kiss off the whole message */
- err_msg (RP_USER, "Unable to parse address");
- if (resync != 0)
- (*resync)();
- continue; /* Go get another address... */
-
- case DONE:
- #ifdef DEBUG
- ll_log( logptr, LLOGFTR, "alst_proc() done");
- #endif
- ap_sqdelete (theptr, (AP_ptr) 0);
- ap_free (theptr);
- return (anybad);
- }
- mgt_inalias = inalias; /* take iniial value */
-
- if(ap_t2s (theptr, &addrp) != (AP_ptr)MAYBE) {
- #ifdef DEBUG
- ll_log (logptr, LLOGBTR, "canonical addr: '%s'", addrp);
- #endif
- if (tracing) {
- printf("%s: ", addrp);
- fflush(stdout);
- }
- ap_t2parts (theptr, (AP_ptr *) 0, (AP_ptr*) 0,
- &local, &domain, &route);
- if (theptr -> ap_obtype == APV_DTYP &&
- lexequ (theptr -> ap_obvalue, "include"))
- {
- Chan *lrval;
- /*
- * Handle :include:/foo/bar@host, :include:file, <file, etc.
- */
- if (domain && (domain -> ap_obvalue)
- && (lrval = ch_h2chan (domain -> ap_obvalue, 1))
- != (Chan *) OK)
- {
- if(lrval == (Chan *)MAYBE)
- retval = RP_NS;
- else {
- cp = multcat (":Include:", local -> ap_obvalue, (char *)0);
- free (local -> ap_obvalue);
- local -> ap_obvalue = cp;
- retval = adr_check (local, domain, route);
- }
- }
- else
- retval = alst_gfil (local -> ap_obvalue);
- }
- else /* regular address */
- retval = adr_check (local, domain, route);
-
- if(rp_gval(retval) == RP_NS) /* can we use the delay channel */
- retval = adr_dsubmit(addrp);
- }
- else
- retval = RP_NS;
-
- if (errabrt) /* we care about this address */
- {
- if (rp_isbad (retval))
- { /* error */
- switch (rp_gval (retval))
- {
- case RP_NS:
- if (tracing) {
- printf("Nameserver Timeout\n");
- fflush(stdout);
- }
- msgptr = "(%s) Nameserver Timeout in \"%s\"";
- if (pro_vfadr) /* just tell caller & continue */
- err_gen(RP_NS, msgptr, rp_valstr(retval), addrp);
- else /* kiss off the whole message */
- err_msg(RP_NS, msgptr, rp_valstr(retval), addrp);
- goto bugout1;
-
- case RP_USER:
- msgptr = "(%s) Unknown user name in \"%s\"";
- break;
-
- case RP_BHST:
- msgptr = "(%s) Unknown host/domain name in \"%s\"";
- break;
-
- case RP_FOPN:
- msgptr = "(%s) Unable to open address file \"%s\"";
- break;
-
- case RP_NAUTH:
- msgptr = "(%s) Bad authorization: %s";
- if (pro_vfadr) /* just tell caller & continue */
- err_gen (RP_USER, msgptr, rp_valstr (retval), auth_msg);
- else /* kiss off the whole message */
- err_msg (RP_USER, msgptr, rp_valstr (retval), auth_msg);
- goto bugout1;
-
- default:
- msgptr = "(%s) Cannot process address \"%s\"";
- }
- if (tracing) {
- printf("Bad address\n");
- fflush(stdout);
- }
- if (pro_vfadr) /* just tell caller & continue */
- err_gen (RP_USER, msgptr, rp_valstr (retval),
- addrp, auth_msg);
- else /* kiss off the whole message */
- err_msg (RP_USER, msgptr, rp_valstr (retval),
- addrp, auth_msg);
- }
- else if (pro_vfadr) {
- /* it's ok and we want to know that, too */
- if (pro_doing) {
- if(rp_gval(retval) == RP_DOK)
- pro_reply (RP_DOK, "Possibly a nice address \"%s\"",
- addrp);
- else
- pro_reply (RP_AOK, "Nice address \"%s\"", addrp);
-
- }
- else
- printf ("%s: OK\n", addrp);
- }
- }
- else if (rp_isbad (retval)) {
- switch (retval)
- {
- case RP_NAUTH:
- case RP_NS:
- anybad = retval;
- break;
-
- default:
- anybad = RP_USER;
- break;
- }
-
- if (badptr) {
- if (*badptr == (char *)0)
- *badptr = multcat(addrp, "\n", (char *) 0);
- else {
- oldbad = *badptr;
- *badptr = multcat(oldbad, addrp, "\n", (char *) 0);
- free (oldbad);
- }
- }
- }
-
- bugout1:
- ap_sqdelete (theptr, (AP_ptr) 0);
- ap_free (theptr);
- free (addrp);
- if (resync != 0)
- (*resync)();
- }
- /* NOTREACHED */
- }
- /******************* ADDRESS FILE INPUT *************************** */
-
- alst_gfil (file) /* read file address list */
- char file[]; /* basic name of file */
- {
- struct stat statbuf;
- int oadruid; /* push old adruid onto stack */
- static char themsg[] = "Can't get addresses from file '%s'";
- char *badlist = (char *) 0;
-
- #ifdef DEBUG
- ll_log (logptr, LLOGBTR, "alst_gfil (%s)", file);
- #endif
- if (tracing) {
- printf("Including file %s\n", file);
- fflush(stdout);
- }
- oadruid = adruid;
-
- if (ap_fpush (file) != OK)
- { /* could not open the file */
- ll_err (logptr, LLOGGEN, themsg, file);
- return (RP_FOPN);
- }
-
- fstat (fileno (ap_fle -> ap_curfp), &statbuf);
-
- if (effecid == statbuf.st_uid)
- adruid = 0; /* full privileges */
- else /* uid for file/process redirection */
- adruid = statbuf.st_uid;
-
- #ifdef DEBUG
- ll_log (logptr, LLOGFTR, "adruid for file = %d", adruid);
- #endif
-
- mgt_inalias = FALSE; /* getting addresses from file */
-
- if (rp_isbad (alst_proc (ap_flget, FALSE, (int (*)())0 , &badlist))) {
- struct passwd *pw;
- char *cp;
- char linebuf[LINESIZE];
-
- ll_log (logptr, LLOGTMP, "Bad address in list-file %s", file);
- if (tracing) {
- printf ("Bad address in file %s\n", file);
- fflush(stdout);
- }
- sprintf (linebuf, "%s %s", locfullname, sitesignature);
- ml_init (NO, NO, linebuf, "Bad address in file");
- ml_adr (supportaddr);
- if( (pw = getpwuid (statbuf.st_uid))
- && (cp = getmailid (pw->pw_name)) )
- ml_adr (cp);
- ml_aend();
- ml_tinit();
- sprintf (linebuf, "Found bad address in the file '%s'.\n\n", file);
- ml_txt (linebuf);
- if (badlist) {
- sprintf (linebuf, "There were problems with:\n");
- ml_txt (linebuf);
- ml_txt (badlist);
- free (badlist);
- sprintf (linebuf,
- "\nThe remaining addresses in the file were used for submission.\n\n");
- ml_txt (linebuf);
- }
- if (ml_end(OK) != OK)
- ll_log (logptr, LLOGFAT, "Can't send to supportaddr");
- }
- ap_fpop ();
-
- #ifdef DEBUG
- ll_log (logptr, LLOGFTR, "done w/file");
- #endif
- adruid = oadruid;
- return (RP_AOK);
- }
- /**************** (tx_) TRANSFER MESSAGE TEXT ******************** */
-
- tx_stormsg () /* store message text into queue */
- { /* perform required processing */
- struct stat statbuf;
- short len,
- retval;
- char linebuf[LINESIZE], /* input line */
- thename[LINESIZE]; /* name of the component */
- register char lastchar; /* to make sure message end with \n */
-
- #ifdef DEBUG
- ll_log (logptr, LLOGPTR, "tx_stormsg ()");
- #endif
-
- mgt_hinit ();
-
- for (mq_txinit (), lastchar = '\n';
- (len = ut_stdin (linebuf, sizeof linebuf, nlnultrm, NOTOK)) != OK &&
- (retval = hdr_proc (linebuf, thename)) > HDR_EOH;
- fputs (linebuf, mq_mffp))
- lastchar = linebuf[len - 1];
- /* process headers & copy to file */
-
- if (lastchar != '\n') /* msgs must end with newline */
- putc ('\n', mq_mffp);
-
- mgt_hend (); /* whatever policies apply overall */
- /* includes Source-Info & Via */
-
- putc ('\n', mq_mffp); /* put out the blank line */
-
- if (retval == HDR_NAM) /* put out illegal first body line */
- fputs (linebuf, mq_mffp); /* if any */
-
- if (!ut_msgend) /* nothing to copy */
- {
- char buf[BUFSIZ]; /* Lets be efficient now */
-
- for (lastchar = '\n'; /* copy the body */
- (len = ut_stdin (buf, sizeof buf, nultrm, OK)) > 0;
- fwrite (buf, sizeof(char), len, mq_mffp))
- lastchar = buf[len - 1];
-
- if (lastchar != '\n') /* msgs must end with newline */
- putc ('\n', mq_mffp);
- }
- fflush (mq_mffp);
- fstat (fileno (mq_mffp), &statbuf);
- tx_msize = st_gsize (&statbuf);
- }
- /******************* (hdr_) PROCESS A HEADER ********************* */
-
- LOCVAR char *hdr_atxt; /* hdr_in() passes to alst() */
-
- LOCFUN
- hdr_in () /* adrs extracted from component text */
- {
- if (hdr_atxt == (char *) 0) /* nothing to give it */
- return (EOF);
-
- switch (*hdr_atxt)
- {
- case '\0':
- case '\n': /* end of string, DROP ON THROUGH */
- hdr_atxt = (char *) 0;
- return (0);
- }
- return (*hdr_atxt++);
- }
- /**/
-
- hdr_proc (theline, name) /* process one header line */
- char theline[], /* the text */
- *name; /* old or new name of header */
- {
- char contents[LINESIZE]; /* where to put header contents */
- int thestate;
-
- #ifdef DEBUG
- ll_log (logptr, LLOGBTR, "hdr_proc (%s)", theline);
- #endif
-
- switch (thestate = hdr_parse (theline, name, contents))
- {
- case HDR_NAM:
- return (HDR_NAM);
-
- case HDR_EOH:
- return (HDR_EOH);
-
- case HDR_NEW:
- case HDR_MOR:
- break;
- }
-
- if (!mgt_hdr (name, contents, thestate))
- err_msg (RP_HUH, "Problem with component '%s'", name);
-
- if (hdr_extractadr && hdr_numadrcmpt > 0 && hdr_isacmpt (name))
- { /* add the addresses */
- hdr_atxt = contents;
- mgt_inalias = FALSE; /* getting addresses from header */
- (void) alst_proc (hdr_in, TRUE, (int (*)())0, (char **) 0);
- }
-
- return (HDR_OK);
- }
-
- LOCFUN
- hdr_isacmpt (name) /* a component on extraction list? */
- register char name[]; /* name of the test component */
- {
- register short entry;
-
- #ifdef DEBUG
- ll_log (logptr, LLOGBTR, "hdr_isacmpt(%s)", name);
- #endif
- for (entry = 0; entry < hdr_numadrcmpt && hdr_cmpt[entry]; entry++)
- if (lexequ (name, hdr_cmpt[entry]))
- return (TRUE);
- return (FALSE);
- }
- /****************** (dlv_) INVOKE DELIVER PROCESS *************** */
-
- dlv_invoke () /* maybe try immediate transmission */
- {
- Chan **chanptr;
- char temppath[LINESIZE];
- char dochans[LINESIZE];
- int oldpid; /* what channels to send */
- int proctyp, /* type of process invocation */
- dowait; /* parent status after child invoke */
-
- #ifdef DEBUG
- ll_log (logptr, LLOGBTR, "dlv_invoke ()");
- #endif
-
- strcpy (dochans, "-c"); /* switch, indicating chans to run */
-
- for (proctyp = dowait = 0, chanptr = ch_tbsrch; *chanptr != 0; chanptr++)
- if ((*chanptr) -> ch_access & DLVRDID)
- {
- #ifdef DEBUG
- ll_log (logptr, LLOGFTR, "do: %s (%s)",
- (*chanptr) -> ch_show, (*chanptr) -> ch_name);
- #endif
- strcat (dochans, (*chanptr) -> ch_name);
- strcat (dochans, ",");
- proctyp = SPNEXEC; /* default to detached send */
- }
- dochans[strlen (dochans) - 1] = '\0'; /* zap last comma */
-
- if (proctyp == 0) /* nothing to send immediately */
- {
- pro_reply (RP_MOK, "Submitted & queued (%s)", mq_munique);
- earlyret = TRUE; /* note that we already ok'd */
- return;
- }
- if (dlv_watch) /* watch immediate transmissions? */
- {
- proctyp = FRKEXEC; /* do it via attached child */
- dowait = FRKWAIT | FRKPIGO;
- /* parent not interruptable til end */
- regfdary[1] = 1;
- }
- else
- {
- pro_reply (RP_MOK, "Submitted & immediates started (%s)", mq_munique);
- earlyret = TRUE; /* note that we already ok'd */
- regfdary[1] = open ("/dev/null", 1);
- /* no output to caller */
- #ifdef DEBUG
- ll_log (logptr, LLOGFTR, "null opened");
- #endif
- }
-
- getfpath (pathdeliver, cmddfldir, temppath);
-
- #ifdef DEBUG
- ll_log (logptr, LLOGBTR,
- "%s (%s, %s)", temppath, mq_munique, dochans);
- #endif
- ll_close (logptr); /* free it for deliver */
-
- oldpid = getpid ();
-
- if (nexecl (proctyp, dowait|FRKCIGO|FRKERRR , regfdary,
- temppath, namdeliver, mq_munique, "-d",
- dochans, (dlv_watch) ? "-w" : (char *)0, (char *)0) == NOTOK)
- if (getpid () != oldpid) /* problem with the child */
- {
- printx ("Problem running delivery process\n");
- ll_err (logptr, LLOGTMP,
- "Unable to run %s '%s'", namdeliver, temppath);
- exit (RP_MECH);
- }
-
- if (regfdary[1] != 1) /* it was opened on /dev/null */
- close (regfdary[1]);
- if (dlv_watch) /* if not already noted */
- pro_reply (RP_MOK, "Done mailing (%s)", mq_munique);
-
- }
- /***************** (err_) GENERAL ERROR-HANDLING ***************** */
-
- /* VARARGS2 */
- err_abrt (code, fmt, b, c, d) /* terminate the process */
- short code; /* a mmdfrply.h termination code */
- char *fmt,
- *b,
- *c,
- *d;
- {
- mq_clear(); /* Just to be sure. */
- if (setjmp (retloc) == 0) /* hack; force err_msg return to here */
- err_msg (code, fmt, b, c, d);
- exit (code); /* pass the reply code to caller */
- }
-
-
- /* VARARGS2 */
- err_msg (code, fmt, b, c, d) /* end processing for current message */
- short code; /* see err_abrt explanation */
- char *fmt,
- *b,
- *c,
- *d;
- {
- #ifdef DEBUG
- ll_log (logptr, LLOGBTR, "err_msg ()");
- #endif
- err_gen (code, fmt, b, c, d); /* includes sending reply */
- if (!ut_eofhit) /* get rid of rest of input stream */
- ut_suckup ();
- mq_clear (); /* eliminate temporary files */
- lnk_freeall(); /* wipe out the current address list */
- if (pro_doing) /* more messages ok in protocl mode */
- longjmp (retloc, TRUE);
- else
- printx ("submit: message submission aborted\n");
- exit (code); /* otherwise, goodbye */
- }
-
- /* VARARGS2 */
- err_gen (code, fmt, b, c, d) /* standard error processing */
- short code; /* see err_abrt, for explanation */
- char *fmt,
- *b,
- *c,
- *d;
- {
- char newfmt[LINESIZE]; /* for printf */
-
- #ifdef DEBUG
- ll_log (logptr, LLOGBTR, "err_gen(%s)", rp_valstr (code));
- #endif
- if (rp_isgood (code)) /* it wasn't an error */
- return;
-
- switch (rp_gval (code)) /* log the error? */
- {
- case RP_HUH: /* not if it was a user error */
- case RP_PARM:
- case RP_USER:
- sprintf (newfmt, "%s %s", "xin", fmt);
- ll_log (logptr, LLOGFST, newfmt, b, c, d);
- break;
-
- default:
- sprintf (newfmt, "%s %s", "err [ ABEND (%s) ] ", fmt);
- ll_err (logptr, LLOGFAT, newfmt, rp_valstr (code), b, c, d);
- }
-
- if (!earlyret) /* haven't already sent reply */
- pro_reply (code, fmt, b, c, d);
- }
- /******************* (ut_) UTILITY ROUTINES ********************** */
-
- ut_stdin (buffer, buflen, brkset, longok) /* read from primary input */
- register char *buffer; /* where to put null-ended input */
- int buflen; /* length of buffer */
- char *brkset; /* what characters to end on */
- int longok; /* long lines are allowed if == OK */
- {
- register int len; /* number of characters read */
-
- /* brkset must always include null ('\000'), which is the end-of-message
- * indicator. if null is the terminator, len is decremented. i.e.,
- * null is not allowed to pass as an input character, tho its occurrence
- * is noted by ut_msgend.
- */
-
- #ifdef DEBUG
- ll_log (logptr, LLOGBTR, "ut_stdin (brk='%s')", brkset);
- #endif
-
- if (ut_msgend || ut_eofhit)
- {
- #ifdef DEBUG
- ll_log (logptr, LLOGBTR, "(eof terminated last read)");
- #endif
- return (0); /* signal eof, for this read */
- }
-
- len = gcread (stdin, buffer, buflen - 1, brkset);
- switch (len)
- {
- case -1:
- err_abrt (RP_LIO, "Error reading data from control stream");
-
- case 0:
- #ifdef DEBUG
- ll_log (logptr, LLOGBTR, "EOF");
- #endif
- ut_msgend =
- ut_eofhit = TRUE;
- buffer[0] = '\0';
- return(0);
- }
- if (longok != OK && len == (buflen - 1))
- err_abrt (RP_NO, "Input line to submit longer than %d characters",
- buflen - 2);
-
- if (isnull (buffer[len - 1])) {
- --len; /* strip null off end */
- ut_msgend = TRUE; /* also note end of message */
- } else
- buffer[len] = '\0';
-
- #ifdef DEBUG
- ll_log (logptr, LLOGFTR, "returning: \"%s\"", buffer);
- #endif
- return (len);
- }
- /**/
-
- ut_suckup () /* skip rest of message input stream */
- { /* to null (not eof) */
- register int c;
-
- if (!ut_msgend && !ut_eofhit)
- {
- while ((c = getc (stdin)) != EOF)
- if (isnull (c) && pro_doing)
- {
- ut_msgend = TRUE;
- return;
- }
- ut_eofhit = TRUE;
- }
- }
-
- char *
- ut_alloc (numbytes) /* allocate some memory */
- unsigned numbytes; /* duh... number of bytes to allocate */
- {
- register char *thebytes;
-
- if ((thebytes = malloc (numbytes)) == NULL)
- err_abrt (RP_MECH, "No more storage available");
- return (thebytes);
- }
-